﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Meta.Numerics.Statistics.Distributions;

namespace ExcelAddIn1
{
    /**
     * Implementation of a single population T-test for the mean.
     */
    class Test_T_SinglePopulation : Test
    {
        public Test_T_SinglePopulation(DataContainer data)
        {
            this.data = data;
            res = new List<String>();
        }

        public override bool EnableMeanDiffField()
        {
            return false;
        }

        public override string GetInfo()
        {
            String s = "Performs a T-test for the mean of a single population. ";
            s += "The test requires that the dataset is normally distributed.";
            return s;
        }

        public override void RunTest()
        {
            res.Add("T-test for the mean");

            //Error check
            if (data.GetNoSets() != 1)
            {
                res.Add("One dataset is required!");
                return;
            }

            String str = (String)Globals.ThisAddIn.Application.InputBox("Select the cells containing the input data", "Input range", Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
            double populationMean = 0.0;
            try
            {
                populationMean = Convert.ToDouble(str);
            }
            catch (FormatException)
            {
                res.Add("Invalid population mean (" + str + ")!");
                return;
            }

            //Get data sets
            DataSet d1 = data.GetDataSet(0);
            int n = d1.GetN();

            //Calculate approximate standard error
            double s = d1.GetStDev() / Math.Sqrt((double)n);
            
            //Calculate T-score of the sample mean
            double T = (d1.GetMean() - populationMean) / s;

            //Get Critical T
            double DF = (double)(n - 1);
            StudentDistribution tdist = new StudentDistribution(DF);
            double TcLeft = tdist.InverseLeftProbability(alpha / 2.0);
            double TcRight = tdist.InverseRightProbability(alpha / 2.0);

            //Calculate P-value
            double p = tdist.RightProbability(T) * 2.0;

            //Results
            res.Add(";" + d1.GetName() + ";-");
            res.Add("N;" + d1.GetN());
            res.Add("Mean;" + d1.GetMean().ToString("F2"));
            res.Add("StDev;" + d1.GetStDev().ToString("F2"));
            res.Add("DoF;" + (int)DF);
            res.Add("α;" + alpha + ";-");
            res.Add("P-value;" + p.ToString("F3"));
            res.Add("T-score;" + T.ToString("F2"));
            res.Add("Tc-low;" + TcLeft.ToString("F2"));
            res.Add("Tc-high;" + TcRight.ToString("F2"));
            if (T < TcLeft || T > TcRight)
            {
                res.Add("Result;The means are different at level " + p.ToString("F3"));
            }
            else
            {
                res.Add("Result;No difference in means (significance level " + p.ToString("F3") + ")");
            }
            res.Add(";;-");
        }
    }
}
